[HVM] Clean up CPUID handling.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 20 Dec 2006 10:09:42 +0000 (10:09 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Wed, 20 Dec 2006 10:09:42 +0000 (10:09 +0000)
From: Xin B Li <xin.b.li@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/hvm.h
xen/include/asm-x86/hvm/vmx/cpu.h

index a4c66ff91a3748f6cc961f86dafb8ac4d8ea846e..b350b3d964e6ffa2c043e978c4a387617dff0a69 100644 (file)
@@ -402,6 +402,47 @@ void hvm_print_line(struct vcpu *v, const char c)
     spin_unlock(&hd->pbuf_lock);
 }
 
+void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
+                                   unsigned int *ecx, unsigned int *edx)
+{
+    if ( !cpuid_hypervisor_leaves(input, eax, ebx, ecx, edx) )
+    {
+        cpuid(input, eax, ebx, ecx, edx);
+
+        if ( input == 0x00000001 )
+        {
+            struct vcpu *v = current;
+
+            clear_bit(X86_FEATURE_MWAIT & 31, ecx);
+
+            if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
+                clear_bit(X86_FEATURE_APIC & 31, edx);
+
+#if CONFIG_PAGING_LEVELS >= 3
+            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
+#endif
+                clear_bit(X86_FEATURE_PAE & 31, edx);
+
+            clear_bit(X86_FEATURE_PSE36 & 31, edx);
+        }
+        else if ( input == 0x80000001 )
+        {
+#if CONFIG_PAGING_LEVELS >= 3
+            struct vcpu *v = current;
+            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
+#endif
+                clear_bit(X86_FEATURE_NX & 31, edx);
+#ifdef __i386__
+            /* Mask feature for Intel ia32e or AMD long mode. */
+            clear_bit(X86_FEATURE_LAHF_LM & 31, ecx);
+
+            clear_bit(X86_FEATURE_LM & 31, edx);
+            clear_bit(X86_FEATURE_SYSCALL & 31, edx);
+#endif
+        }
+    }
+}
+
 typedef unsigned long hvm_hypercall_t(
     unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
 
index 55b631660ecbfade5ed87817c60526aad585db44..a5f39dacdf9447f31be70fd0f4e4257a2513126b 100644 (file)
@@ -999,91 +999,65 @@ static void svm_do_general_protection_fault(struct vcpu *v,
 /* Reserved bits EDX: [31:29], [27], [22:20], [18], [10] */
 #define SVM_VCPU_CPUID_L1_EDX_RESERVED 0xe8740400
 
-static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input, 
-                                struct cpu_user_regs *regs) 
+static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb,
+                                struct cpu_user_regs *regs)
 {
+    unsigned long input = regs->eax;
     unsigned int eax, ebx, ecx, edx;
-    unsigned long eip;
     struct vcpu *v = current;
     int inst_len;
 
     ASSERT(vmcb);
 
-    eip = vmcb->rip;
+    hvm_cpuid(input, &eax, &ebx, &ecx, &edx);
 
-    HVM_DBG_LOG(DBG_LEVEL_1, 
-                "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
-                " (esi) %lx, (edi) %lx",
-                (unsigned long)regs->eax, (unsigned long)regs->ebx,
-                (unsigned long)regs->ecx, (unsigned long)regs->edx,
-                (unsigned long)regs->esi, (unsigned long)regs->edi);
+    if ( input == 0x00000001 )
+    {
+        /* Clear out reserved bits. */
+        ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED;
+        edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED;
 
-    if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
+        /* Guest should only see one logical processor.
+         * See details on page 23 of AMD CPUID Specification.
+         */
+        clear_bit(X86_FEATURE_HT & 31, &edx);  /* clear the hyperthread bit */
+        ebx &= 0xFF00FFFF;  /* clear the logical processor count when HTT=0 */
+        ebx |= 0x00010000;  /* set to 1 just for precaution */
+    }
+    else if ( input == 0x80000001 )
     {
-        cpuid(input, &eax, &ebx, &ecx, &edx);       
-        if (input == 0x00000001 || input == 0x80000001 )
-        {
-            if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
-            {
-                /* Since the apic is disabled, avoid any confusion 
-                   about SMP cpus being available */
-                clear_bit(X86_FEATURE_APIC, &edx);
-            }
+        if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
+            clear_bit(X86_FEATURE_APIC & 31, &edx);
+
 #if CONFIG_PAGING_LEVELS >= 3
-            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
+        if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
 #endif
-            {
-                clear_bit(X86_FEATURE_PAE, &edx);
-                if (input == 0x80000001 )
-                   clear_bit(X86_FEATURE_NX & 31, &edx);
-            }
-            clear_bit(X86_FEATURE_PSE36, &edx);
-            if (input == 0x00000001 )
-            {
-                /* Clear out reserved bits. */
-                ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED;
-                edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED;
+            clear_bit(X86_FEATURE_PAE & 31, &edx);
 
-                clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
+        clear_bit(X86_FEATURE_PSE36 & 31, &edx);
 
-                /* Guest should only see one logical processor.
-                 * See details on page 23 of AMD CPUID Specification. 
-                 */
-                clear_bit(X86_FEATURE_HT, &edx);  /* clear the hyperthread bit */
-                ebx &= 0xFF00FFFF;  /* clear the logical processor count when HTT=0 */
-                ebx |= 0x00010000;  /* set to 1 just for precaution */
-            }
-            else
-            {
-                /* Clear the Cmp_Legacy bit 
-                 * This bit is supposed to be zero when HTT = 0.
-                 * See details on page 23 of AMD CPUID Specification. 
-                 */
-                clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
-                /* Make SVM feature invisible to the guest. */
-                clear_bit(X86_FEATURE_SVME & 31, &ecx);
-#ifdef __i386__
-                /* Mask feature for Intel ia32e or AMD long mode. */
-                clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx);
-
-                clear_bit(X86_FEATURE_LM & 31, &edx);
-                clear_bit(X86_FEATURE_SYSCALL & 31, &edx);
-#endif
-                /* So far, we do not support 3DNow for the guest. */
-                clear_bit(X86_FEATURE_3DNOW & 31, &edx);
-                clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
-            }
-        }
-        else if ( ( input == 0x80000007 ) || ( input == 0x8000000A  ) )
-        {
-            /* Mask out features of power management and SVM extension. */
-            eax = ebx = ecx = edx = 0;
-        }
-        else if ( input == 0x80000008 )
-        {
-            /* Make sure Number of CPU core is 1 when HTT=0 */
-            ecx &= 0xFFFFFF00; 
-        }
+        /* Clear the Cmp_Legacy bit
+         * This bit is supposed to be zero when HTT = 0.
+         * See details on page 23 of AMD CPUID Specification.
+         */
+        clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
+
+        /* Make SVM feature invisible to the guest. */
+        clear_bit(X86_FEATURE_SVME & 31, &ecx);
+
+        /* So far, we do not support 3DNow for the guest. */
+        clear_bit(X86_FEATURE_3DNOW & 31, &edx);
+        clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
+    }
+    else if ( input == 0x80000007 || input == 0x8000000A )
+    {
+        /* Mask out features of power management and SVM extension. */
+        eax = ebx = ecx = edx = 0;
+    }
+    else if ( input == 0x80000008 )
+    {
+        /* Make sure Number of CPU core is 1 when HTT=0 */
+        ecx &= 0xFFFFFF00;
     }
 
     regs->eax = (unsigned long)eax;
@@ -1091,17 +1065,11 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
     regs->ecx = (unsigned long)ecx;
     regs->edx = (unsigned long)edx;
 
-    HVM_DBG_LOG(DBG_LEVEL_1, 
-                "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, "
-                "ebx=%x, ecx=%x, edx=%x",
-                eip, input, eax, ebx, ecx, edx);
-
     inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
     ASSERT(inst_len > 0);
     __update_guest_eip(vmcb, inst_len);
 }
 
-
 static inline unsigned long *get_reg_p(unsigned int gpreg, 
                                        struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
 {
@@ -2828,7 +2796,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
         goto exit_and_crash;
 
     case VMEXIT_CPUID:
-        svm_vmexit_do_cpuid(vmcb, regs->eax, regs);
+        svm_vmexit_do_cpuid(vmcb, regs);
         break;
 
     case VMEXIT_HLT:
index c95afe5b83dc9deb948ef69fa3dd88995ae5026a..06edb02fe6b56ad7ff1380a66bcd27f03efba1e6 100644 (file)
@@ -899,24 +899,14 @@ static void vmx_do_no_device_fault(void)
     }
 }
 
-#define bitmaskof(idx) (1U << ((idx)&31))
+#define bitmaskof(idx)  (1U << ((idx) & 31))
 static void vmx_do_cpuid(struct cpu_user_regs *regs)
 {
     unsigned int input = (unsigned int)regs->eax;
     unsigned int count = (unsigned int)regs->ecx;
     unsigned int eax, ebx, ecx, edx;
-    unsigned long eip;
-    struct vcpu *v = current;
-
-    eip = __vmread(GUEST_RIP);
-
-    HVM_DBG_LOG(DBG_LEVEL_3, "(eax) 0x%08lx, (ebx) 0x%08lx, "
-                "(ecx) 0x%08lx, (edx) 0x%08lx, (esi) 0x%08lx, (edi) 0x%08lx",
-                (unsigned long)regs->eax, (unsigned long)regs->ebx,
-                (unsigned long)regs->ecx, (unsigned long)regs->edx,
-                (unsigned long)regs->esi, (unsigned long)regs->edi);
 
-    if ( input == CPUID_LEAF_0x4 )
+    if ( input == 0x00000004 )
     {
         cpuid_count(input, count, &eax, &ebx, &ecx, &edx);
         eax &= NUM_CORES_RESET_MASK;
@@ -929,6 +919,7 @@ static void vmx_do_cpuid(struct cpu_user_regs *regs)
          */
         u64 value = ((u64)regs->edx << 32) | (u32)regs->ecx;
         unsigned long mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
+        struct vcpu *v = current;
         char *p;
 
         gdprintk(XENLOG_INFO, "Input address is 0x%"PRIx64".\n", value);
@@ -946,72 +937,37 @@ static void vmx_do_cpuid(struct cpu_user_regs *regs)
         unmap_domain_page(p);
 
         gdprintk(XENLOG_INFO, "Output value is 0x%"PRIx64".\n", value);
-        ecx = (u32)(value >>  0);
+        ecx = (u32)value;
         edx = (u32)(value >> 32);
-    }
-    else if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
-    {
-        cpuid(input, &eax, &ebx, &ecx, &edx);
+    } else {
+        hvm_cpuid(input, &eax, &ebx, &ecx, &edx);
 
-        if ( input == CPUID_LEAF_0x1 )
+        if ( input == 0x00000001 )
         {
             /* Mask off reserved bits. */
             ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED;
 
-            if ( vlapic_hw_disabled(vcpu_vlapic(v)) )
-                clear_bit(X86_FEATURE_APIC, &edx);
-
-#if CONFIG_PAGING_LEVELS >= 3
-            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
-#endif
-                clear_bit(X86_FEATURE_PAE, &edx);
-            clear_bit(X86_FEATURE_PSE36, &edx);
-
             ebx &= NUM_THREADS_RESET_MASK;
 
             /* Unsupportable for virtualised CPUs. */
-            ecx &= ~(bitmaskof(X86_FEATURE_VMXE)  |
-                     bitmaskof(X86_FEATURE_EST)   |
-                     bitmaskof(X86_FEATURE_TM2)   |
-                     bitmaskof(X86_FEATURE_CID)   |
-                     bitmaskof(X86_FEATURE_MWAIT) );
-
-            edx &= ~( bitmaskof(X86_FEATURE_HT)   |
-                     bitmaskof(X86_FEATURE_ACPI)  |
-                     bitmaskof(X86_FEATURE_ACC) );
-        }
-        else if (  ( input == CPUID_LEAF_0x6 )
-                || ( input == CPUID_LEAF_0x9 )
-                || ( input == CPUID_LEAF_0xA ))
-        {
-            eax = ebx = ecx = edx = 0x0;
+            ecx &= ~(bitmaskof(X86_FEATURE_VMXE) |
+                     bitmaskof(X86_FEATURE_EST)  |
+                     bitmaskof(X86_FEATURE_TM2)  |
+                     bitmaskof(X86_FEATURE_CID));
+
+            edx &= ~(bitmaskof(X86_FEATURE_HT)   |
+                     bitmaskof(X86_FEATURE_ACPI) |
+                     bitmaskof(X86_FEATURE_ACC));
         }
-        else if ( input == CPUID_LEAF_0x80000001 )
-        {
-#if CONFIG_PAGING_LEVELS >= 3
-            if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
-#endif
-                clear_bit(X86_FEATURE_NX & 31, &edx);
-#ifdef __i386__
-            clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx);
 
-            clear_bit(X86_FEATURE_LM & 31, &edx);
-            clear_bit(X86_FEATURE_SYSCALL & 31, &edx);
-#endif
-        }
+        if ( input == 0x00000006 || input == 0x00000009 || input == 0x0000000A )
+            eax = ebx = ecx = edx = 0x0;
     }
 
-    regs->eax = (unsigned long) eax;
-    regs->ebx = (unsigned long) ebx;
-    regs->ecx = (unsigned long) ecx;
-    regs->edx = (unsigned long) edx;
-
-    HVM_DBG_LOG(DBG_LEVEL_3, "eip@%lx, input: 0x%lx, "
-                "output: eax = 0x%08lx, ebx = 0x%08lx, "
-                "ecx = 0x%08lx, edx = 0x%08lx",
-                (unsigned long)eip, (unsigned long)input,
-                (unsigned long)eax, (unsigned long)ebx,
-                (unsigned long)ecx, (unsigned long)edx);
+    regs->eax = (unsigned long)eax;
+    regs->ebx = (unsigned long)ebx;
+    regs->ecx = (unsigned long)ecx;
+    regs->edx = (unsigned long)edx;
 }
 
 #define CASE_GET_REG_P(REG, reg)    \
index fb1dac3c463088926f644cffedb6342ba2695917..b41c84b526059acce760a96f39073e987bb07a43 100644 (file)
@@ -219,6 +219,8 @@ hvm_get_segment_register(struct vcpu *v, enum x86_segment seg,
     hvm_funcs.get_segment_register(v, seg, reg);
 }
 
+void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
+                                   unsigned int *ecx, unsigned int *edx);
 void hvm_stts(struct vcpu *v);
 void hvm_set_guest_time(struct vcpu *v, u64 gtime);
 void hvm_freeze_time(struct vcpu *v);
index 8c214ae1ce5cae8416fb0d21e6738972572dd9a7..c988b1334323c445e24af4643f63725b29741946 100644 (file)
@@ -32,21 +32,14 @@ struct arch_state_struct {
 #define VMX_MF_32       1
 #define VMX_MF_64       2
 
-#define CPUID_LEAF_0x1        0x1
-#define CPUID_LEAF_0x4        0x4
-#define CPUID_LEAF_0x6        0x6
-#define CPUID_LEAF_0x9        0x9
-#define CPUID_LEAF_0xA        0xA
-#define CPUID_LEAF_0x80000001 0x80000001
-
 #define NUM_CORES_RESET_MASK                 0x00003FFF
 #define NUM_THREADS_RESET_MASK               0xFF00FFFF
 
 #define VMX_VCPU_CPUID_L1_ECX_RESERVED_18    0x00040000
 #define VMX_VCPU_CPUID_L1_ECX_RESERVED_6     0x00000040
 
-#define VMX_VCPU_CPUID_L1_ECX_RESERVED             \
-            ( VMX_VCPU_CPUID_L1_ECX_RESERVED_18  | \
-              VMX_VCPU_CPUID_L1_ECX_RESERVED_6   )
+#define VMX_VCPU_CPUID_L1_ECX_RESERVED              \
+            ( VMX_VCPU_CPUID_L1_ECX_RESERVED_18 |   \
+              VMX_VCPU_CPUID_L1_ECX_RESERVED_6 )
 
 #endif /* __ASM_X86_HVM_VMX_CPU_H__ */